package com.jz.dsq.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.jz.dsq.condition.Condition;
import com.jz.dsq.exception.DsqException;


import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zhangliang
 */
public class DsqUtil {


    public static final String WAVY = "~";

    /**
     * 验证字段名合法是否合法
     *
     * @param entityClass :
     * @param fieldName   :
     * @return void
     * @author zhangliang
     * @date 2020-10-09 下午 13:27
     */
    public static void validateFieldKey(String fieldName, Class<?> entityClass) {
        boolean check;
        if (fieldName.contains(StrUtil.DOT)) {
            String[] names = StrUtil.split(fieldName, StrUtil.DOT);
            if (names.length > 1) {
                // 循环判断字段是否存在
                for (String name : names) {
                    // 获取字段类型
                    Field field = ReflectUtil.getField(entityClass, name);
                    // 判断是否存在该字段
                    if (field == null) {
                        throw new DsqException("查询字段[" + name + "]不存在与" + entityClass.getName());
                    }
                    entityClass = field.getType();
                    if (entityClass.equals(List.class) || entityClass.equals(Set.class) || entityClass.equals(Map.class)) {
                        Type type = field.getGenericType();
                        if (type instanceof ParameterizedType) {
                            ParameterizedType pt = (ParameterizedType) type;
                            // 得到泛型里的class类型对象
                            entityClass = (Class<?>) pt.getActualTypeArguments()[0];
                        }
                    }
                }
            }
        } else {
            check = ReflectUtil.hasField(entityClass, fieldName);
            if (!check) {
                throw new DsqException("查询字段[" + fieldName + "]不存在与" + entityClass.getName());
            }
        }
    }

    /**
     * 防SQL注入
     *
     * @param likeStr :
     * @return java.lang.String
     * @author zhangliang
     * @date 2020-10-09 下午 13:27
     */
    public static String escapeSqlLike(Object likeStr) {
        String str = likeStr.toString();
        str = StrUtil.replace(str, "_", "/_");
        str = StrUtil.replace(str, "%", "/%");
        str = StrUtil.replace(str, "/", "//");
        return str;
    }


    /**
     * 根据是否有动态操作进行构建查询条件
     *
     * @param condition
     * @param fieldClass
     * @author zhangliang
     */
    public static void dynamicallyGenerateQueryConditions(Condition condition, Class<?> fieldClass) {
        //适配无sql操作 ，动态生成查询条件
        if (fieldClass.equals(String.class)) {
            condition.setValue(specialStrKeyword((String) condition.getValue()));
            condition.setOperator(Operator.like);
        } else if (fieldClass.equals(Date.class)) {
            dateTypeToArray(fieldClass, condition);
            condition.setOperator(Operator.between);
        } else if (fieldClass.equals(Boolean.class)) {
            condition.setValue(Convert.toBool(condition.getValue()));
        } else {
            condition.setOperator(Operator.eq);
        }
    }

    /**
     * 日期类型转数组处理
     *
     * @param fieldClass
     * @param condition
     * @author zhangliang
     */
    public static void dateTypeToArray(Class<?> fieldClass, Condition condition) {
        if (fieldClass.equals(Date.class)) {
            Assert.isTrue(condition.getValue().toString().contains(WAVY),
                    "字段[{}]是日期类型,[{}]值不符合传参规范:{}{}{}",
                    condition.getKey(), condition.getValue(),
                    DatePattern.NORM_DATETIME_PATTERN, WAVY, DatePattern.NORM_DATETIME_PATTERN);
            String[] valueArr = condition.getValue().toString().split(WAVY);
            if (ArrayUtil.isNotEmpty(valueArr)) {
                Date[] dateArray = new Date[]{Convert.toDate(valueArr[0]), Convert.toDate(valueArr[1])};
                condition.setValue(dateArray);
            }
        }
    }


    /**
     * 模糊查询
     */
    public static String specialStrKeyword(String str) {
        if (StrUtil.isBlank(str)) {
            return null;
        }
        StringBuilder stringBuffer = new StringBuilder(str);
        int length = str.length();
        for (int i = 0; i < length; i++) {
            char chari = stringBuffer.charAt(i);
            if (i == 0) {
                if (chari == '%' || chari == '_' || chari == '\\') {
                    stringBuffer.insert(i, "\\");
                    i++;
                    length++;
                }
            } else {
                if (chari == '%' || chari == '_' || chari == '\\') {
                    stringBuffer.insert(i, "%\\");
                    i += 2;
                    length += 2;
                } else {
                    stringBuffer.insert(i, "%");
                    i++;
                    length++;
                }
            }
        }
        return stringBuffer.toString();
    }
}
